package com.rs;

import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

import com.rs.cache.loaders.ItemDefinitions;
import com.rs.cache.loaders.NPCDefinitions;
import com.rs.cache.loaders.ObjectDefinitions;
import com.rs.cores.CoresManager;
import com.rs.game.Region;
import com.rs.game.World;
import com.rs.game.grandexchange.GrandExchangeDatabase;
import com.rs.game.player.Player;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;
import com.rs.game.worldlist.WorldList;
import com.rs.net.ServerChannelHandler;
import com.rs.utils.AutoBackup;
import com.rs.utils.DTRank;
import com.rs.utils.DisplayNames;
import com.rs.utils.EconomyPrices;
import com.rs.utils.IPBanL;
import com.rs.utils.Logger;
import com.rs.utils.PkRank;
import com.rs.utils.RemoveObjects;
import com.rs.utils.SerializableFilesManager;
import com.rs.utils.Text;
import com.rs.utils.Utils;

public final class Launcher {

	public static AutoBackup autoBackup = new AutoBackup();

	public static void main(String[] args) throws Exception {
		if (args.length < 3) {
			System.out.println("USE: guimode(boolean) debug(boolean) hosted(boolean)");
			return;
		}
		Settings.HOSTED = Boolean.parseBoolean(args[2]);
		Settings.DEBUG = Boolean.parseBoolean(args[1]);
		long currentTime = Utils.currentTimeMillis();
		Logger.log("Launcher", "Loading " + Settings.SERVER_NAME + ", please wait...");
		Initializer.loadFiles();
		addUpdatePlayersOnlineTask();
		try {
			Logger.log("Launcher", "Initing Server Channel Handler...");
			ServerChannelHandler.init();
			cleanHome();
			EconomyPrices.init();
			WorldList.init();
			Text.init();
			GrandExchangeDatabase.init();
		} catch (Throwable e) {
			Logger.handle(e);
			Logger.log("Launcher", "Failed initing Server Channel Handler. Shutting down...");
			System.exit(1);
		}
		// Panel frame = new Panel();
		// frame.setVisible(true);
		long endTime = Utils.currentTimeMillis();
		long totalTime = TimeUnit.MILLISECONDS.toSeconds((endTime - currentTime));
		Logger.log("Launcher", "Server took " + totalTime + " second" + (totalTime == 1 ? "" : "s") + " to launch.");
		if (Settings.HOSTED) {
			addAccountsSavingTask();
			addCleanMemoryTask();
			addProcessGrandExchangeTask();
		}
	}

	private static void addProcessGrandExchangeTask() {
		CoresManager.slowExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					GrandExchangeDatabase.processOffers();
				} catch (Throwable e) {
					Logger.handle(e);
				}
			}
		}, 0, 1, TimeUnit.MINUTES);
	}
	
	private static void addCleanMemoryTask() {
		CoresManager.slowExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					cleanMemory(Runtime.getRuntime().freeMemory() < Settings.MIN_FREE_MEM_ALLOWED);
				} catch (Throwable e) {
					Logger.handle(e);
				}
			}
		}, 0, 10, TimeUnit.MINUTES);
	}

	private static void addAccountsSavingTask() {
		CoresManager.slowExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					saveFiles();
				} catch (Throwable e) {
					Logger.handle(e);
				}

			}
		}, 5, 30, TimeUnit.SECONDS);
	}

	public static void saveFiles() {
		for (Player player : World.getPlayers()) {
			if (player == null || !player.hasStarted() || player.hasFinished())
				continue;
			SerializableFilesManager.savePlayer(player);
		}
		DisplayNames.save();
		IPBanL.save();
		PkRank.save();
		DTRank.save();
	}

	public static void cleanHome() {
		WorldTasksManager.schedule(new WorldTask() {
			@Override
			public void run() {
				if (World.getPlayers().size() > 0) {
					RemoveObjects.removeObjects();
					stop();
				}
			}
		}, 0, 2);
	}

	public static void cleanMemory(boolean force) {
		if (force) {
			ItemDefinitions.clearItemsDefinitions();
			NPCDefinitions.clearNPCDefinitions();
			ObjectDefinitions.clearObjectDefinitions();
			for (Region region : World.getRegions().values()) {
				region.removeMapFromMemory();
			}
			System.gc();
		}
	}

	public static void shutdown() {
		try {
			closeServices();
		} finally {
			System.exit(0);
		}
	}

	public static void closeServices() {
		ServerChannelHandler.shutdown();
		CoresManager.shutdown();
	}

	public static void restart() {
		closeServices();
		System.gc();
		try {
			Runtime.getRuntime().exec("java -server -Xms2048m -Xmx20000m -cp bin;/data/libs/netty-3.2.6.Final.jar;/data/libs/FileStore.jar Launcher false false true false");
			System.exit(0);
		} catch (Throwable e) {
			Logger.handle(e);
		}

	}

	private static void setWebsitePlayersOnline(int amount) throws IOException {
		URL url = new URL("http://www.geryonrs.com/register.php?amount=" + amount + "&auth=GHUsfaUEjC82X");
		url.openStream().close();
	}

	private static void addUpdatePlayersOnlineTask() {
		CoresManager.slowExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					setWebsitePlayersOnline(World.getPlayers().size());
				} catch (Throwable e) {
					// Logger.handle(e);
				}
			}
		}, 2, 2, TimeUnit.MINUTES);
	}

	private Launcher() {

	}

}
